Tutorials

Author

Dionne Argyropoulos

Published

July 30, 2025

Load the Package and Data

devtools::install_github("dionnecargy/SeroTrackR") # To download the package

── R CMD build ─────────────────────────────────────────────────────────────────
* checking for file ‘/private/var/folders/bh/0yzt0_x97vj_zktb_39c1xvh0000gn/T/RtmppUUMqe/remotes176d13bd77268/dionnecargy-SeroTrackR-f0ad9fc/DESCRIPTION’ ... OK
* preparing ‘SeroTrackR’:
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
Omitted ‘LazyData’ from DESCRIPTION
* building ‘pvsero_0.3.0.tar.gz’
library(SeroTrackR) # To load the package 
library(tidyverse) # for data wrangling and visualisation
library(knitr)    # for RMarkdown visualisation and PDF generation

Data Analysis: runPvSeroPipeline()

Run this global function runPvSeroPipeline() embedded within the {SeroTrackR} R package! This function contains all of the steps in order of how to perform the Plasmodium vivax serology test and treat protocol as found in our application!

Using Tutorial Dataset: Load the Data

We will be using the build-in files in the R package for this tutorial, as shown below.

your_raw_data <- c(
  system.file("extdata", "example_MAGPIX_plate1.csv", package = "SeroTrackR"),
  system.file("extdata", "example_MAGPIX_plate2.csv", package = "SeroTrackR"), 
  system.file("extdata", "example_MAGPIX_plate3.csv", package = "SeroTrackR")
)
your_plate_layout <- system.file("extdata", "example_platelayout_1.xlsx", package = "SeroTrackR")

To run your OWN data, follow the code below and uncomment (i.e., remove the hashtags):

# your_raw_data <- c(
#   "PATH/TO/YOUR/FILE/plate1.csv",
#   "PATH/TO/YOUR/FILE/plate2.csv",
#   "PATH/TO/YOUR/FILE/plate3.csv"
# )
# your_plate_layout <- "PATH/TO/YOUR/FILE/plate_layout.xlsx"

Run Classification: Yes

final_analysis <- runPvSeroPipeline(
  raw_data = your_raw_data, 
  plate_layout = your_plate_layout, 
  platform = "magpix", 
  location = "ETH", 
  experiment_name = "experiment1", 
  classify = "Yes", 
  algorithm_type = "antibody_model", 
  sens_spec = "maximised"
)

Classification

This is a table containing the classification results (seropositive or seronegative) for each SampleID. In this case, the classification results are stored in the pred_class_max column as we chose the sens_spec = "maximised". If you change it to another type of threshold, then the suffix of that column will change accordingly.

You will also see the relative antibody unit (RAU) values (columns with antigen names), whether the sample passed QC check (QC_total) and the plate that they were run on.

final_analysis[[1]] %>%
  head() %>% 
  kable()
SampleID Plate QC_total EBP LF005 LF010 LF016 MSP8 PTEX150 PvCSS RBP2b.P87 pred_class_max
ABC013 plate1 pass 0.0003339 0.0015045 0.0002163 0.0014567 0.0000195 0.0001591 0.0000772 0.0003714 seropositive
ABC097 plate2 pass 0.0004324 0.0015615 0.0001944 0.0013373 0.0000195 0.0001549 0.0000705 0.0009189 seropositive
ABC181 plate3 pass 0.0003822 0.0015832 0.0002144 0.0013711 0.0000195 0.0001582 0.0000710 0.0002070 seropositive
ABC022 plate1 pass 0.0200000 0.0200000 0.0007373 0.0194885 0.0006247 0.0003145 0.0006008 0.0004895 seropositive
ABC106 plate2 pass 0.0057123 0.0193731 0.0007458 0.0195240 0.0006263 0.0003077 0.0006480 0.0126203 seropositive
ABC190 plate3 pass 0.0098260 0.0200000 0.0007400 0.0200000 0.0006020 0.0003171 0.0006555 0.0175253 seropositive

Standard Curve Plot

The standard curve plots are generated from the antibody data from the standards you indicated in your plate layout (e.g. S1-S10) and Median Fluorescent Intensity (MFI) units are displayed in log10-scale. In the case of the PvSeroTaT multi-antigen panel, the antigens will be displayed and in general your standard curves should look relatively linear (only when the y-axis is on logarithmic scale).

final_analysis[[2]]

Bead Counts QC Plot

A summary of the bead counts for each plate well are displayed, with blue indicating there are sufficient beads (≥15) or red when there are not enough. If any of the wells are red, they should be double-checked manually and re-run on a new plate if required.

The function will inform you whether there are “No repeats necessary” or provide a list of samples to be re-run. In the example data, the beads in plate 2 wells A1 and A2 will need to be repeated

final_analysis[[3]] # Plot

final_analysis[[4]] # Samples to repeat 
# A tibble: 2 × 4
  Location SampleID Plate  QC   
  <chr>    <chr>    <chr>  <chr>
1 A1       Blank1   plate2 fail 
2 A2       Blank2   plate2 fail 

Blanks QC Plot

The Median Fluorescent Intensity (MFI) units for each antigen is displayed for your blank samples. In general, each blank sample should have ≤50 MFI for each antigen, if they are higher they should be cross-checked manually.

In the example data, blank samples recorded higher MFI values for LF005 on plate 1 and should be checked to confirm this is expected from the assay.

final_analysis[[5]]

Model Output Plot

The automated data processing in this app allows you to convert your Median Fluorescent Intensity (MFI) data into Relative Antibody Units (RAU) by fitting a 5-parameter logistic function to the standard curve on a per-antigen level. The results from this log-log conversion should look relatively linear for each antigen.

final_analysis[[6]]
$plate1


$plate2


$plate3

Run Classification: No

no_classification_final_analysis <- runPvSeroPipeline(
  raw_data = your_raw_data, 
  plate_layout = your_plate_layout, 
  platform = "magpix", 
  location = "ETH", 
  experiment_name = "experiment1", 
  classify = "No", ########################## key if you do NOT want any classification performed i.e., you do not have PvSeroTaT antigens 
  algorithm_type = "antibody_model", 
  sens_spec = "maximised"
)

MFI and RAU Data

no_classification_final_analysis[[1]]  %>%
  head() %>% 
  kable()
SampleID Plate QC_total EBP_MFI EBP_Dilution LF005_MFI LF005_Dilution LF010_MFI LF010_Dilution LF016_MFI LF016_Dilution MSP8_MFI MSP8_Dilution PTEX150_MFI PTEX150_Dilution PvCSS_MFI PvCSS_Dilution RBP2b.P87_MFI RBP2b.P87_Dilution
ABC013 plate1 pass 2712 0.0003339 1569.0 0.0015045 673 0.0002163 327 0.0014567 182.0 1.95e-05 936.0 0.0001591 223 0.0000772 1068.0 0.0003714
ABC014 plate1 pass 134 0.0000216 378.0 0.0004204 117 0.0000277 197 0.0010331 58.0 1.95e-05 122.0 0.0000225 93 0.0000298 465.5 0.0001536
ABC015 plate1 pass 182 0.0000232 209.0 0.0002466 208 0.0000616 374 0.0015985 221.5 1.95e-05 293.0 0.0000535 868 0.0002235 463.0 0.0001527
ABC016 plate1 pass 152 0.0000222 229.5 0.0002688 101 0.0000244 89 0.0005994 48.0 1.95e-05 109.0 0.0000220 110 0.0000383 591.0 0.0001989
ABC017 plate1 pass 1135 0.0001478 236.0 0.0002758 299 0.0000950 507 0.0019840 209.5 1.95e-05 1665.5 0.0002668 266 0.0000893 671.0 0.0002277
ABC018 plate1 pass 174 0.0000229 395.0 0.0004370 175 0.0000460 78 0.0005452 70.0 1.95e-05 294.5 0.0000537 92 0.0000296 103.0 0.0000238

QC Plots

Repeat the same steps as above to find the QC plots!

#### Standard Curve Plot
no_classification_final_analysis[[2]]

#### Bead Counts QC Plot
no_classification_final_analysis[[3]] # Plot

no_classification_final_analysis[[4]] # Samples to repeat 
# A tibble: 2 × 4
  Location SampleID Plate  QC   
  <chr>    <chr>    <chr>  <chr>
1 A1       Blank1   plate2 fail 
2 A2       Blank2   plate2 fail 
#### Blanks QC Plot
no_classification_final_analysis[[5]]

#### Model Output Plot
no_classification_final_analysis[[6]]
$plate1


$plate2


$plate3

Create a PDF Report

renderQCReport(
  your_raw_data, 
  your_plate_layout, 
  "magpix", 
  location = "ETH"
)

  |                                                     
  |                                               |   0%
  |                                                     
  |...                                            |   7%                       
  |                                                     
  |......                                         |  13% [setup]               
  |                                                     
  |.........                                      |  20%                       
  |                                                     
  |.............                                  |  27% [standard curves plot]

  |                                                     
  |................                               |  33%                       
  |                                                     
  |...................                            |  40% [model results plot]  

  |                                                     
  |......................                         |  47%                       
  |                                                     
  |.........................                      |  53% [bead counts plot]    

  |                                                     
  |............................                   |  60%                       
  |                                                     
  |...............................                |  67% [check repeats table] 
  |                                                     
  |..................................             |  73%                       
  |                                                     
  |......................................         |  80% [blank samples plot]  

  |                                                     
  |.........................................      |  87%                       
  |                                                     
  |............................................   |  93% [plate layouts]       
  |                                                     
  |...............................................| 100%                       
                                                                                                                 
/Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/x86_64/pandoc +RTS -K512m -RTS template.knit.md --to latex --from markdown+autolink_bare_uris+tex_math_single_backslash --output /Users/Dionne/Documents/GitHub/SeroTrackR/experiment1_20250730_ETH_v1.3.1_QCreport.tex --lua-filter /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/library/rmarkdown/rmarkdown/lua/pagebreak.lua --lua-filter /Library/Frameworks/R.framework/Versions/4.4-x86_64/Resources/library/rmarkdown/rmarkdown/lua/latex-div.lua --embed-resources --standalone --highlight-style tango --pdf-engine pdflatex --variable graphics --include-in-header /var/folders/bh/0yzt0_x97vj_zktb_39c1xvh0000gn/T//RtmppUUMqe/rmarkdown-str176d157a9b255.html --variable 'geometry:margin=1in' --include-in-header /var/folders/bh/0yzt0_x97vj_zktb_39c1xvh0000gn/T//RtmppUUMqe/rmarkdown-str176d145fb1769.html 

Data Analysis: Pk/Pv/Pf

5-Point Standard Curve

Step 1: Load your data!

Firstly, we will be using our example data that’s in-built in the package. Here replace the system.file() argument with the file path for your package.

your_raw_data_5std <- c(
  system.file("extdata", "example_MAGPIX_pk_5std_plate1.csv", package = "SeroTrackR"),
  system.file("extdata", "example_MAGPIX_pk_5std_plate2.csv", package = "SeroTrackR")
)
your_plate_layout_5std <- system.file("extdata", "example_platelayout_pk_5std.xlsx", package = "SeroTrackR")

Step 2: Read your data and process MFI to RAU

Caitlin and Dionne have worked on a function to (a) process raw Serological data and (b) convert MFI to RAU. The runPlasmoSero5point() function will output three data frames: (i) Results from MAGPIX (MFI), (ii), Counts for each sample, (iii) Processed RAU values for each sample. These dataframes can be used for further analysis and can be transformed as you wish.

pk_analysis_1 <- runPlasmoSero5point(
  raw_data = your_raw_data_5std, 
  platform = "magpix", 
  plate_layout = your_plate_layout_5std, 
  date = "2025-07-30" # Optional: This will default to today's date
)

Standard Curve Plot: One Curve

As requested, this is a plot of ONE standard curve which you will specify. You can modify this plot as you see fit by piping other ggplot2() arguments.

plotOneStdCurve(pk_analysis_1, "plate1")

Standard Curve Plot: Compare Two Curves

This function allows you to plot all of your standard curves.

plotManyStdCurves(pk_analysis_1)

10-Point Standard Curve

These steps are very similar to the 5-point standard curve, except here we use the runPlasmoSero10point() function.

Step 1: Load your data!

your_raw_data_10std <- c(
  system.file("extdata", "example_MAGPIX_pk_10std_plate1.csv", package = "SeroTrackR"),
  system.file("extdata", "example_MAGPIX_pk_10std_plate2.csv", package = "SeroTrackR")
)
your_plate_layout_10std <- system.file("extdata", "example_platelayout_pk_10std.xlsx", package = "SeroTrackR")

Step 2: Read your data and process MFI to RAU

pk_analysis_2 <- runPlasmoSero10point(
  raw_data = your_raw_data_10std, 
  platform = "magpix", 
  plate_layout = your_plate_layout_10std, 
  date = "2025-07-30" # Optional: This will default to today's date
)

Standard Curve Plot: One Curve

plotOneStdCurve(pk_analysis_2, "plate1")

Standard Curve Plot: Compare Two Curves

plotManyStdCurves(pk_analysis_2)

Visualisation of the {SeroTrackR} R Package

We have used the {targets} R package to generate a pipeline! This allows us to:

  • Automatically detect the dependencies of each step
  • One-command execution
  • Automatic caching
  • Automatic detection of changes in data and/or code

For more information on {targets} see this tutorial.

here() starts at /Users/Dionne/Documents/GitHub/SeroTrackR
✔ skipped pipeline [42ms, 15 skipped]
Warning message:
package ‘targets’ was built under R version 4.4.1 
here() starts at /Users/Dionne/Documents/GitHub/SeroTrackR
Warning message:
package ‘targets’ was built under R version 4.4.1